/**
 * 
 */
package com.trungkent.smsbackup.util;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

import android.content.ContentResolver;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.provider.ContactsContract;
import android.widget.ImageView;

/**
 * @author setamember
 * 
 */
public class LoadImageFromContact {
	private ContentResolver mContentResolver;
	private static Bitmap mPlaceHolder;
	static Map<String, Bitmap> imageCache;

	public LoadImageFromContact(Bitmap placeHolder) {
		mPlaceHolder = placeHolder;
		imageCache = new HashMap<String, Bitmap>();
	}

	public void loadImage(String photoUri, ImageView imageView) {
		mContentResolver = imageView.getContext().getContentResolver();

		if (cancelPotentialDownload(photoUri, imageView)) {
			// Is the bitmap in our memory cache?
			Bitmap bitmap = null;
			bitmap = (Bitmap) imageCache.get(photoUri);

			if (bitmap == null) {
				GetImageFromContact getImageFromContact = new GetImageFromContact(
						imageView);
				DownloadedDrawable downloadedDrawable = new DownloadedDrawable(
						getImageFromContact);
				imageView.setImageDrawable(downloadedDrawable);

				getImageFromContact.execute(photoUri);
			} else {
				imageView.setImageBitmap(bitmap);
			}

		}

	}

	private class GetImageFromContact extends AsyncTask<String, Void, Bitmap> {
		private String photoUri;
		private WeakReference<ImageView> imageViewReference;

		private GetImageFromContact(ImageView imageView) {
			imageViewReference = new WeakReference<ImageView>(imageView);
		}

		@Override
		protected Bitmap doInBackground(String... params) {
			photoUri = (String) params[0];
			return loadImage(mContentResolver, photoUri);
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
		 */
		@Override
		protected void onPostExecute(Bitmap result) {
			super.onPostExecute(result);

			if (imageViewReference != null) {
				ImageView photoViewer = imageViewReference.get();

				GetImageFromContact getImageFromContact = getImageFromContact(photoViewer);
				if (this == getImageFromContact) {
					photoViewer.setImageBitmap(result);
				}

			}

			if (result != null) {
				imageCache.put(photoUri, result);
				if (result.isRecycled()) {
					result.recycle();
					result = null;
				}
			}
		}

	}

	// gets an existing download if one exists for the imageview
	private static GetImageFromContact getImageFromContact(ImageView imageView) {
		if (imageView != null) {
			Drawable drawable = imageView.getDrawable();
			if (drawable instanceof DownloadedDrawable) {
				DownloadedDrawable downloadedDrawable = (DownloadedDrawable) drawable;
				return downloadedDrawable.getBitmapDownloaderTask();
			}
		}
		return null;
	}

	static class DownloadedDrawable extends BitmapDrawable {
		private final WeakReference<GetImageFromContact> bitmapDownloaderTaskReference;

		public DownloadedDrawable(GetImageFromContact getImageFromContact) {
			super(null, mPlaceHolder);
			bitmapDownloaderTaskReference = new WeakReference<GetImageFromContact>(
					getImageFromContact);
		}

		public GetImageFromContact getBitmapDownloaderTask() {
			return bitmapDownloaderTaskReference.get();
		}
	}

	// cancel a download (internal only)
	private static boolean cancelPotentialDownload(String url,
			ImageView imageView) {
		GetImageFromContact bitmapDownloaderTask = getImageFromContact(imageView);
		if (bitmapDownloaderTask != null) {
			String bitmapUrl = bitmapDownloaderTask.photoUri;
			if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
				bitmapDownloaderTask.cancel(true);
			} else {
				return false;
			}
		}
		return true;
	}

	static Bitmap loadImage(ContentResolver contentResolver, String photoUri) {
		byte[] photoBytes = null;

		Cursor c = contentResolver.query(Uri.parse(photoUri),
				new String[] { ContactsContract.CommonDataKinds.Photo.PHOTO },
				null, null, null);

		try {
			if (c.moveToFirst())
				photoBytes = c.getBlob(0);

		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();

		} finally {

			c.close();
		}

		if (photoBytes != null) {
			return BitmapFactory.decodeByteArray(photoBytes, 0,
					photoBytes.length);
		}

		return null;
	}
}
